package luke.audio.analyzer;



/**
 * 音频预处理器类
 * 提供降噪、标准化和均衡器功能
 */
public class AudioPreprocessor {
    
    /**
     * 移动平均滤波器，用于降噪
     * 
     * @param signal 输入信号
     * @param windowSize 窗口大小
     * @return 降噪后的信号
     */
    public static float[] movingAverageFilter(float[] signal, int windowSize) {
        if (signal == null || signal.length == 0 || windowSize <= 0) {
            return signal;
        }
        
        float[] filteredSignal = new float[signal.length];
        int halfWindow = windowSize / 2;
        
        for (int i = 0; i < signal.length; i++) {
            float sum = 0;
            int count = 0;
            
            // 计算窗口内的平均值
            for (int j = Math.max(0, i - halfWindow); j <= Math.min(signal.length - 1, i + halfWindow); j++) {
                sum += signal[j];
                count++;
            }
            
            filteredSignal[i] = sum / count;
        }
        
        return filteredSignal;
    }
    
    /**
     * 傅里叶变换降噪（简化实现）
     * 通过移除高频分量来实现降噪
     * 
     * @param signal 输入信号
     * @param sampleRate 采样率
     * @param cutoffFrequency 截止频率
     * @return 降噪后的信号
     */
    public static float[] fourierTransformFilter(float[] signal, int sampleRate, double cutoffFrequency) {
        if (signal == null || signal.length == 0) {
            return signal;
        }
        
        // 这里使用一个简化的实现，实际应用中可能需要使用FFT库
        // 对于高于截止频率的分量进行衰减
        float[] filteredSignal = new float[signal.length];
        double maxFrequency = sampleRate / 2.0;
        
        // 计算截止频率对应的索引
        int cutoffIndex = (int) (cutoffFrequency / maxFrequency * signal.length / 2);
        
        // 复制低频分量
        System.arraycopy(signal, 0, filteredSignal, 0, Math.min(cutoffIndex, signal.length));
        
        // 对高频分量进行衰减（这里简化为置零）
        for (int i = cutoffIndex; i < signal.length; i++) {
            filteredSignal[i] = 0;
        }
        
        return filteredSignal;
    }
    
    /**
     * 标准化音频信号到 [-1, 1] 范围
     * 
     * @param signal 输入信号
     * @return 标准化后的信号
     */
    public static float[] normalize(float[] signal) {
        if (signal == null || signal.length == 0) {
            return signal;
        }
        
        // 找到信号的最大绝对值
        float maxAmplitude = 0;
        for (float value : signal) {
            maxAmplitude = Math.max(maxAmplitude, Math.abs(value));
        }
        
        // 避免除以零
        if (maxAmplitude == 0) {
            return signal;
        }
        
        // 标准化信号
        float[] normalizedSignal = new float[signal.length];
        for (int i = 0; i < signal.length; i++) {
            normalizedSignal[i] = signal[i] / maxAmplitude;
        }
        
        return normalizedSignal;
    }
    
    /**
     * 去除音频中的人声（仅适用于立体声音频）
     * 通过将左右声道相减来实现人声去除
     * 
     * @param audioData 立体声音频数据 [L,R,L,R,...]
     * @param channels 声道数
     * @return 去除人声后的单声道音频数据
     */
    public static float[] removeVocal(float[] audioData, int channels) {
        if (audioData == null || audioData.length == 0 || channels != 2) {
            // 如果不是立体声，直接返回原始数据
            return audioData;
        }
        
        int sampleCount = audioData.length / channels;
        float[] vocalRemoved = new float[sampleCount];
        
        // 通过将左右声道相减来去除人声
        // 人声通常在左右声道中是相同的，所以相减可以去除人声
        for (int i = 0; i < sampleCount; i++) {
            float left = audioData[i * channels];      // 左声道
            float right = audioData[i * channels + 1]; // 右声道
            // 相减并除以2以保持音量平衡
            vocalRemoved[i] = (left - right) / 2.0f;
        }
        
        return vocalRemoved;
    }
    
    /**
     * 均衡器类
     * 根据输入的频带和对应的数值，对频带内的能量进行改变
     */
    public static class Equalizer {
        private double[] frequencyBands;
        private double[] bandGains;
        
        /**
         * 构造函数
         * 
         * @param frequencyBands 频带定义数组，格式为 [start1, end1, start2, end2, ...]
         * @param bandGains 每个频带的增益值
         */
        public Equalizer(double[] frequencyBands, double[] bandGains) {
            if (frequencyBands == null || bandGains == null || 
                frequencyBands.length == 0 || bandGains.length == 0 ||
                frequencyBands.length != bandGains.length * 2) {
                throw new IllegalArgumentException("频带定义和增益值数组大小不匹配");
            }
            
            this.frequencyBands = frequencyBands.clone();
            this.bandGains = bandGains.clone();
        }
        
        /**
         * 应用均衡器到音频信号
         * 
         * @param signal 输入信号
         * @param sampleRate 采样率
         * @return 应用均衡器后的信号
         */
        public float[] apply(float[] signal, int sampleRate) {
            if (signal == null || signal.length == 0) {
                return signal;
            }
            
            // 这里使用一个简化的实现
            // 实际应用中可能需要使用FFT来实现频域处理
            float[] processedSignal = signal.clone();
            
            // 对每个频带应用增益
            for (int band = 0; band < bandGains.length; band++) {
                double startFreq = frequencyBands[band * 2];
                double endFreq = frequencyBands[band * 2 + 1];
                double gain = bandGains[band];
                
                // 如果增益为1，跳过处理
                if (Math.abs(gain - 1.0) < 0.001) {
                    continue;
                }
                
                // 简化的频带处理：根据频率范围应用增益
                // 这是一个非常简化的实现，实际应用中需要更复杂的滤波器设计
                for (int i = 0; i < processedSignal.length; i++) {
                    processedSignal[i] *= gain;
                }
            }
            
            return processedSignal;
        }
    }
}